#pragma once

#include <string>
#include <windows.h>
#include <winhttp.h>

#pragma comment(lib, "winhttp.lib")

#define ASYNC_WINHTTP_OK 0
#define ASYNC_WINHTTP_ERROR 1

class AsyncWinHttpErrorInfo
{
public:
	AsyncWinHttpErrorInfo() : status_(ASYNC_WINHTTP_OK) {}
	~AsyncWinHttpErrorInfo() {}

	void set(const int& status, const std::wstring& desc)
	{
		status_ = status;
		desc_ = desc;
	}

	int Status() { return status_; }
	std::wstring Desc() { return desc_; }

private:
	int status_;
	std::wstring desc_;
};

class AsyncWinHttp;

typedef void (*ASYNC_WINHTTP_CALLBACK)(AsyncWinHttp*);

class AsyncWinHttp
{
public:
	AsyncWinHttp();
	virtual ~AsyncWinHttp();

	bool Initialize(ASYNC_WINHTTP_CALLBACK cb, void * pHandle, LPWSTR fn, DWORD timeout);
	bool SendRequest(LPWSTR szURL);
	void GetResponse(std::wstring& str) const;
	void GetResponseHeader(std::wstring& str) const;
    void GetResponseRaw(std::string& str) const;
    LPSTR GetResponsePtr() const;
    DWORD GetResponseLen() const;
    //LPSTR GetResponseBuffer() const;
    void SetOutFileName(LPWSTR fn);
	bool SetTimeout(DWORD timeout);

	AsyncWinHttpErrorInfo status;
    void *    hEvent_;
private:
	HINTERNET session_;
	HINTERNET connect_;       // Connection handle
	HINTERNET request_;       // Resource request handle
	DWORD     size_;          // Size of the latest data block
	DWORD     totalSize_;     // Size of the total data
    LPSTR    lpBuffer_;      // Buffer for storing read data
    LPWSTR    lpOutFileName_;    // output file pointer.
	WCHAR     memo_[256];     // String providing state information
	ASYNC_WINHTTP_CALLBACK cb_;

	std::wstring response_;
	std::wstring responseHeader_;
	std::string* response_raw_;

	bool Header();
	LPCWSTR GetApiErrorString(DWORD dwResult);
	bool ReadData();
	bool QueryData();
	void Cleanup();
	void TransferAndDeleteBuffers(LPSTR lpReadBuffer, DWORD dwBytesRead);

	static void __stdcall AsyncCallback(HINTERNET hInternet, DWORD_PTR dwContext,
		DWORD dwInternetStatus,
		LPVOID lpvStatusInformation,
		DWORD dwStatusInformationLength);
};

